use std::collections::HashMap;

use toml::Table;

mod local;
#[macro_use]
mod pick;
mod remote;

pub async fn diff(proxy: Option<&str>) -> anyhow::Result<()> {
    let remote_str = remote::remote_str(proxy).await?;
    let local_str = local::local_str()?;
    let remote_config = toml::from_str::<Table>(&remote_str)?;
    let local_config = toml::from_str::<Table>(&local_str)?;
    let diff = grammar(&remote_config, &local_config)
        .ok_or("比较Grammer时出错")
        .unwrap();
    let count = diff.len();
    diff.iter()
        .for_each(|(_key, value)| println!("{:#?}", value));
    println!("总共有{}个不同的设置", count);
    Ok(())
}

fn grammar<'a>(
    remote: &'a Table,
    local: &'a Table,
) -> Option<HashMap<&'a str, (&'a str, &'a str, &'a str, &'a str)>> {
    let remote = remote.get("grammar")?;
    let local = local.get("grammar")?;
    let remote = remote.as_array().map(|array| pick_grammar(array));
    println!("remote is {:?}", remote);
    let local = local.as_array().map(|array| pick_grammar(array));
    if let Some((remote, local)) = combine_option!(remote, local) {
        let map = remote
            .into_iter()
            .filter(|(key, value)| {
                let grammar = local.get(key);
                grammar != Some(value)
            })
            .collect::<HashMap<_, _>>();
        Some(map)
    } else {
        None
    }
}

fn pick_grammar(array: &[toml::Value]) -> HashMap<&str, (&str, &str, &str, &str)> {
    array
        .iter()
        .filter_map(|v| {
            let name = pick!(v, "name");
            let git = pick!(v, "source", "git");
            let rev = pick!(v, "source", "rev");
            let subpath = pick!(v, "source", "subpath");
            let subpath = subpath.or(Some(""));
            combine_option!(name, git, rev, subpath)
        })
        .map(|value| {
            let key = value.0;
            (key, value)
        })
        .collect::<HashMap<_, _>>()
}
